﻿
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;

using n_MyControl;
using n_GroupControl;

using n_ModuleLibDecoder;
using n_GUIcoder;
using n_HardModule;
using n_MainSystemData;
using n_OS;
using n_TypeControl;

namespace n_App
{
public partial class MainForm : Form
{
	static UserControl[] MyControlList;
	static int Length;
	
	static TypeControl[] TypeControlList;
	static int TypeControlLength;
	
	public static MainForm mf;
	
	MySControl mymouseOnObj;
	public MySControl MouseOnObj {
		set {
			if( mymouseOnObj == value ) {
				return;
			}
			if( mymouseOnObj != null ) {
				mymouseOnObj.CancelMouseOn();
			}
			mymouseOnObj = value;
			if( value != null ) {
				mymouseOnObj.SetMouseOn();
				int Idx = int.Parse( mymouseOnObj.Name );
				
				
				
				if( mymouseOnTypeObj != null ) {
					mymouseOnTypeObj.CancelMouseOn();
				}
				TypeControlList[Idx].SetMouseOn();
				mymouseOnTypeObj = TypeControlList[Idx];
				panelList.Select();
			}
		}
		get {
			return mymouseOnObj;
		}
	}
	
	TypeControl mymouseOnTypeObj;
	public TypeControl MouseOnTypeObj {
		set {
			MouseOnObj = null;
			if( mymouseOnTypeObj == value ) {
				return;
			}
			if( mymouseOnTypeObj != null ) {
				mymouseOnTypeObj.CancelMouseOn();
			}
			mymouseOnTypeObj = value;
			if( value != null ) {
				mymouseOnTypeObj.SetMouseOn();
				panelGroup.Select();
			}
		}
		get {
			return mymouseOnTypeObj;
		}
	}
	
	MySControl myselectObj;
	public MySControl SelectObj {
		set {
			if( myselectObj == value ) {
				return;
			}
			if( myselectObj != null ) {
				myselectObj.CancelSelect();
			}
			myselectObj = value;
			if( value != null ) {
				myselectObj.SetSelect();
			}
			timer1.Enabled = false;
		}
		get {
			return myselectObj;
		}
	}
	
	TypeControl myselectTypeObj;
	public TypeControl SelectTypeObj {
		set {
			if( myselectTypeObj == value ) {
				return;
			}
			if( myselectTypeObj != null ) {
				myselectTypeObj.CancelSelect();
			}
			myselectTypeObj = value;
			if( value != null ) {
				myselectTypeObj.SetSelect();
				
				CY = int.Parse( myselectTypeObj.Name.Split( ' ' )[1] );
				
				//系统自动取负数
				LastY = -mf.panelList.AutoScrollPosition.Y;
				timer1.Enabled = true;
			}
		}
		get {
			return myselectTypeObj;
		}
	}
	
	float LY;
	float CY;
	
	static bool OK = false;
	
	string ExampleLib;
	
	//构造函数
	public MainForm()
	{
		//
		// The InitializeComponent() call is required for Windows Forms designer support.
		//
		InitializeComponent();
		
		n_OS.OS.Init();
		SystemData.Load();
		
		mf = this;
		
		MyControlList = new UserControl[500];
		Length = 0;
		
		TypeControlList = new TypeControl[20];
		TypeControlLength = 0;
		
		isMouseDown = false;
		LastY = 0;
		
		panelList.MouseDown += new MouseEventHandler( MyMouseDown );
		panelList.MouseMove += new MouseEventHandler( MyMouseMove );
		panelList.MouseUp += new MouseEventHandler( MyMouseUp );
		
		panelList.MouseEnter += new EventHandler( MyMouseEnter );
		
		MouseOnObj = null;
		SelectObj = null;
		
		panelList.Select();
		
		ExampleLib = "";
		
		//注意: 标题名字只能有一行, 文字描述可以有多行
		
		AddGroup( "linkboy生态资源汇总" );
			AddNodeDir( "linkboyWIFI安卓调试助手", "linkboy官方出品的wifi调试APP" );
			AddNodeDir( "linkboy主板开源生产资料", "面向电子模块厂家的开源资料包" );
			AddNodeDir( "自定义模块的制作和添加", "linkboy中没有的模块可自行制作添加" );
			AddNodeDir( "第三方厂商库汇总", "查看和添加第三方厂商库的模块" );
		
		AddGroup( "1 linkboy软件入门" );
			AddNodePdf( "1软件介绍", "整体介绍linkboy软件的使用方式" );
			AddNodePdf( "2体验入门", "讲解软件的界面及常用操作" );
			AddNodePdf( "3常用操作", "讲解各类逻辑和功能指令的用法" );
	
		AddGroup( "1 linkboy软件入门(旧版本)" );
			AddNodeWord( "1 linkboy体验入门", "整体介绍linkboy软件的使用方式" );
			AddNodeWord( "2 linkboy界面操作概述", "讲解软件的界面及常用操作" );
			AddNodeWord( "3 linkboy指令用法说明", "讲解各类逻辑和功能指令的用法" );
			AddNodeWord( "4 linkboy用户自定义指令说明", "讲解用户自定义指令的各种用法" );
			AddNodeWord( "5 linkboy元素用法说明", "讲解数值量、条件量等内置元素的用法" );
			AddNodeWord( "6 linkboy模块用法说明", "综合介绍模块库的内容和用法" );
		
			AddGroup( "2 linkboy编程基础" );
			AddNodePdf( "1初识编程", "讲解编程启蒙" );
			AddNodePdf( "2有限次数循环", "让一段程序执行有限次数" );
			AddNodePdf( "3无限循环", "反复执行一段程序" );
			AddNodePdf( "4条件判断", "根据条件执行不同的指令" );
			AddNodePdf( "5变量", "存放用户的数据" );
			AddNodePdf( "6算数运算", "对数据进行各种处理" );
			AddNodePdf( "7逻辑运算", "多个条件的复合判断" );
			AddNodePdf( "8布尔值", "条件判断结果的表示方法" );
			AddNodePdf( "9条件循环", "有条件的循环执行一段程序" );
			AddNodePdf( "10等待条件成立", "条件等待语句" );
			AddNodePdf( "11break和continue", "如何退出循环和跳过本次循环" );
			AddNodePdf( "12无参函数", "也就是用户自定义的指令" );
			AddNodePdf( "13带参函数", "带有参数的用户自定义指令" );
			AddNodePdf( "14函数返回值", "自定义指令返回一个数据" );
			AddNodePdf( "15多线程（事件）", "让多个程序同时执行" );
		
		AddGroup( "3 linkboy常用软件模块使用" );
			AddNodeWord( "滤波器", "传感器读取的数值的软件滤波" );
			AddNodeWord( "数据映射器", "数值从一个区间变换到另一个区间" );
			AddNodeWord( "随机数产生器", "介绍如何获取随机数并使用" );
		
		AddGroup( "4 linkboy编程技能提高笔记" );
			AddNodeWord( "按钮的高级用法", "包括长按，短按，单击，双击，复用，切换等" );
			AddNodeWord( "事件触发和多线程协同", "介绍linkboy的底层运行框架，工作机制" );
			
		AddGroup( "nano转UNO扩展面包板课程" );
			AddNodePPT( "软件入门", "整体介绍linkboy软件的使用方式", null );
			AddNodePPT( "红绿交通灯", "一个简单的马路交通信号灯", null );
			AddNodePPT( "震动防盗报警器", "发生震动时就会播放警笛声", null );
			AddNodePPT( "电子门铃", "按下按钮播放门铃声", null );
			AddNodePPT( "节日彩灯", "随机变换颜色的彩灯", null );
			AddNodePPT( "红外遥控彩灯", "红外遥控器控制彩灯颜色", null );
			AddNodePPT( "光控音乐盒", "随光线强度变化而播放不同的音乐", null );
			AddNodePPT( "倒计时秒表", "具有倒计时功能的秒表作品", null );
			AddNodePPT( "表情包显示器", "可以显示8X8的点阵图片", null );
		//AddGroup( "UNO面包板课程" );
		//	AddNodePPT( "查看温度模块曲线", "通过电脑显示温度的变化曲线图" );
		
		AddGroup( "RISC-V国产处理器案例(GD32)" );
			AddNodeWord( "8X8点阵屏显示笑脸图案", "RISC-V的入门课程" );
			AddNodeWord( "俄罗斯方块(RISC-V版)", "基于RISC-V和游戏框架搭建" );
			AddNodeWord( "使用python玩转RISC-V", "基于RISC-V 验证我们的自研python解释器" );
			AddNodeWord( "linkboy+小熊派物联网开发", "小熊派入门课程" );
		
		AddGroup( "手机wifi控制马达系列" );
			AddNodeWord( "第一课 串口通信助手测试ESP8266", "讲解如何设置wifi模块的工作模式及收发数据" );
			AddNodeWord( "入门示例-手机控制主板指示灯", "通过手机控制主板上的指示灯" );
			AddNodeWord( "手机双按钮控制两个LED亮灭", "通过手机控制两个独立LED亮灭" );
			AddNodeWord( "手机滑动条控制彩灯颜色", "通过手机调节彩灯颜色" );
			AddNodeWord( "手机控制双路马达", "通过手机控制两个马达正反转" );
		
		AddGroup( "手机wifi通信系列" );
			AddNodePdf( "1ESP8266无线通信", "讲解如何设置wifi模块的工作模式及收发数据" );
			AddNodePdf( "2无线遥控灯", "通过手机控制主板上的指示灯" );
			AddNodePdf( "3环境温度监测", "通过手机显示温度数据" );
			
		AddGroup( "手机wifi通信（专用扩展板）" );
			AddNodeWord( "第一课 串口通信助手测试ESP8266", "讲解如何设置wifi模块的工作模式及收发数据" );
			AddNodeWord( "第二课 手机控制主板指示灯", "通过手机控制主板上的指示灯" );
			AddNodeWord( "第三课 发送传感器数据到手机", "手机界面显示传感器数据" );
			
		AddGroup( "框架类-贝壳物联" );
			AddNodeWord( "关于贝壳物联框架升级通知", "增加版本号和断线重连" );
			AddNodeWord( "第一课 贝壳物联初体验", "体验通过贝壳物联控制主板" );
			AddNodeWord( "第二课 开始第一个物联网小作品", "通过手机控制主板上的指示灯" );
			AddNodeWord( "第三课 上传数据到手机", "手机界面显示传感器数据" );
		
		AddGroup( "贝壳物联教程PPT版" );
			AddNodePdf( "1远程物联网", "讲解如何连接到互联网" );
			AddNodePdf( "2远程遥控灯", "通过远程控制指示灯" );
			AddNodePdf( "3远程温度监测", "上传温度传感器数据" );
			
		AddGroup( "项目式课程" );
			AddNodeWord( "炫彩音乐播放器", "介绍双按键控制彩灯与音乐" );
			AddNodeWord( "脉搏检测器", "测量脉搏并通过电脑屏幕显示出波形" );
			AddNodeWord( "七彩音乐盒", "音乐小屋- 彩灯随音乐节拍而变换" );
			AddNodeWord( "艺术范的电子表", "谁说理工男没有情调~" );
			AddNodeWord( "光敏小星星", "天黑之后, LED小星星们就会随着音乐节拍闪动" );
			AddNodeWord( "液晶屏温湿度计", "液晶屏显示中文和温湿度数据" );
			AddNodeWord( "8X8点阵表情指示器", "简单有趣的8*8点阵显示图片作品" );
			AddNodeWord( "数码显示温度计", "超低成本的小小温度计, 温度精确到一位小数~" );
			AddNodeWord( "液晶点阵广告屏", "超级迷你的广告显示器, 可以放到书包上" );
			//AddNodeWord( "自己做的计算器!", "挑战一下你的编程潜力吧少年!" );
			AddNodePdf( "计算器程序详解", "详细讲解一个计算器程序的编写过程" );
		
		AddGroup( "电子游戏类" );
			AddNodeWord( "5步教你做贪吃蛇游戏", "循序渐进, 从0开始完成贪吃蛇游戏, 小白可入" );
			AddNodeWord( "俄罗斯方块游戏机", "硬核编程, 小白勿入" );
			AddNodeWord( "俄罗斯方块游戏机升级版", "基于游戏框架升级, 小白勿入" );
		
		AddGroup( "专家课程类" );
			AddNodeDir( "自研python编程示范", "展示自研python编译/解释器的使用" );
			AddNodeDir( "代码编程示例", "代码硬核编程, 小白勿入" );
		
		AddGroup( "linkboy集成电路实验室" );
			AddNodePPT( "linkboy集成电路科普课程", "搭建简单的逻辑门电路并仿真", @"example\电路仿真\" );
			AddNodePPT( "自制简易CPU课程", "从零开始教你做一个CPU!", @"example\电路仿真\A设计简易CPU课程\" );
			
		GroupControl mm = new GroupControl( mf.panelList );
		mm.Name = "0";
		mm.SetName( "结束" );
		MyControlList[Length] = mm;
		Length++;
		mf.panelList.Controls.Add( mm );
		
		n_App.Program.ExampleBox.ResetLib( ExampleLib, "study" );
		
		
		Resfresh();
		
		
		OK = true;
	}
	
	//添加条目
	string LastGroupName;
	void AddGroup( string Name )
	{
		LastGroupName = Name;
		
		GroupControl mm = new GroupControl( mf.panelList );
		mm.Name = TypeControlLength.ToString();
		mm.SetName( Name );
		MyControlList[Length] = mm;
		Length++;
		mf.panelList.Controls.Add( mm );
		
		TypeControl l = new TypeControl( mf.panelGroup );
		//l.SetImage( bmp );
		l.SetName( Name );
		
		//l.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
		l.Name = (Length - 1).ToString() + " 0";
		
		TypeControlList[TypeControlLength] = l;
		++TypeControlLength;
		mf.panelGroup.Controls.Add( l );
		
		/*
		//在指定目录及子目录下查找文件,在list中列出子目录及文件
		DirectoryInfo Dir = new DirectoryInfo( OS.SystemRoot + "arduino-ext" + OS.PATH_S + Name + OS.PATH_S );
		DirectoryInfo[] DirSub = Dir.GetDirectories();
		
		AddNode( "基础", Dir + @"\0.lab" );
		
		//遍历当前文件夹中的所有文件
		foreach( FileInfo f in Dir.GetFiles("*.lab", SearchOption.TopDirectoryOnly) ) {
			string FileName = f.ToString();
			
			if( FileName == "0.lab" ) {
				continue;
			}
			string FilePath = Dir + @"\" + FileName;
			AddNode( FileName.Remove( FileName.Length - 4, 4 ), FilePath );
		}
		*/
	}
	
	//添加条目-Dir
	void AddNodeDir( string Name, string mes )
	{
		//string iPath = OS.SystemRoot + "arduino-ext\\8X8LED点阵扩展\\0.png";
		//Bitmap bmp = new Bitmap( iPath );
		
		MySControl uc = new MySControl( mf.panelList, MySControl.WType.Dir );
		
		uc.Name = (TypeControlLength-1).ToString();
		uc.SetName( Name );
		uc.SetExample( LastGroupName + Name );
		uc.SetMes( mes );
		uc.SetGroup( LastGroupName );
		
		MyControlList[Length] = uc;
		Length++;
		mf.panelList.Controls.Add( uc );
		
		uc.SetNoExam();
	}
	
	//添加条目-Word
	void AddNodeWord( string Name, string mes )
	{
		AddNodeFile_inner( Name, mes, MySControl.WType.Word, null );
	}
	
	//添加条目-Pdf
	void AddNodePdf( string Name, string mes )
	{
		AddNodeFile_inner( Name, mes, MySControl.WType.Pdf, null );
	}
	
	//添加条目-Pdf
	void AddNodePPT( string Name, string mes, string exdir )
	{
		AddNodeFile_inner( Name, mes, MySControl.WType.PPT, exdir );
	}
	
	//添加条目-文档类
	void AddNodeFile_inner( string Name, string mes, MySControl.WType wt, string extDir )
	{
		//string iPath = OS.SystemRoot + "arduino-ext\\8X8LED点阵扩展\\0.png";
		//Bitmap bmp = new Bitmap( iPath );
		
		MySControl uc = new MySControl( mf.panelList, wt );
		
		uc.Name = (TypeControlLength-1).ToString();
		uc.SetName( Name );
		uc.SetExample( LastGroupName + Name );
		uc.SetMes( mes );
		uc.SetGroup( LastGroupName );
		uc.SetExDir( extDir );
		
		MyControlList[Length] = uc;
		Length++;
		mf.panelList.Controls.Add( uc );
		
		
		string Fold = OS.SystemRoot + "study" + OS.PATH_S + LastGroupName + OS.PATH_S + Name + OS.PATH_S;
		if( !Directory.Exists( Fold ) ) {
			uc.SetNoExam();
			return;
		}
		
		DirectoryInfo Dir = new DirectoryInfo( Fold );
		ExampleLib += LastGroupName + Name + "\n";
		
		//遍历当前文件夹中的所有文件
		foreach( FileInfo f in Dir.GetFiles("*.lab", SearchOption.TopDirectoryOnly) ) {
			string FileName = f.ToString();
			ExampleLib += "\t" + LastGroupName + OS.PATH_S + Name + OS.PATH_S + FileName + "\n";
		}
	}
	
	//调整位置
	void Resfresh()
	{
		panelList.AutoScrollPosition = new Point( 0, 0 );
		
		if( this.WindowState == FormWindowState.Minimized ) {
			return;
		}
		
		int n = (panelList.Width - 20) / (191+10);
		if( n == 0 ) {
			n = 1;
		}
		
		int ii = 0;
		int Hei = 8;
		int LHeight = 0;
		
		//居中
		//int Start = (panelList.Width - (191 + 10) * n) / 2 + 5;
		//左对齐
		int Start = 0;
		
		for( int i = 0; i < Length; ++i ) {
			UserControl uc = MyControlList[i];
			if( uc is GroupControl ) {
				if( ii != 0 ) {
					ii = 0;
					Hei += LHeight + 8 + 20;
				}
				else {
					Hei += 20;
				}
				uc.Location = new Point( 0, Hei );
				uc.Width = panelList.Width - 20;
				Hei += uc.Height + 8;
			}
			else {
				uc.Location = new Point( Start + ii * (uc.Width+10), Hei );
				++ii;
				if( ii == n ) {
					ii = 0;
					Hei += uc.Height + 8;
				}
			}
			LHeight = uc.Height;
		}
		
		
		//int ph = (panelGroup.Height - 10) / LabelLength;
		int ph = TypeControlList[0].Height + 4;
		
		for( int i = 0; i < TypeControlLength; ++i ) {
			TypeControl l = TypeControlList[i];
			l.Location = new Point( 2, i * ph + 2 );
			//l.Width = panelGroup.Width - 30;
			//l.Height = ph;
			//l.Width = panelGroup.Width;
			int ind = int.Parse( l.Name.Split( ' ' )[0] );
			l.Name = ind + " " + (((GroupControl)MyControlList[ind]).Location.Y).ToString();
		}
	}
	
	//-------------------------------------
	
	bool isMouseDown;
	int LastY;
	int lastScroll;
	
	void MyMouseDown(object sender, MouseEventArgs e)
	{
		timer1.Enabled = false;
		isMouseDown = true;
		Point p = panelList.AutoScrollPosition;
		lastScroll = -p.Y;
		
		LastY = e.Y;
	}
	
	void MyMouseMove(object sender, MouseEventArgs e)
	{
		if( isMouseDown ) {
			int off = e.Y - LastY;
			panelList.AutoScrollPosition = new Point( 0, lastScroll - off );
		}
	}
	
	void MyMouseUp(object sender, MouseEventArgs e)
	{
		isMouseDown = false;
	}
	
	void MyMouseEnter(object sender, EventArgs e)
	{
		n_App.MainForm.mf.MouseOnObj = null;
		panelList.Select();
	}
	
	void MyTypeMouseEnter(object sender, EventArgs e)
	{
		n_App.MainForm.mf.MouseOnTypeObj = null;
		panelGroup.Select();
	}
	
	//-------------------------------------
	
	void MainFormSizeChanged(object sender, EventArgs e)
	{
		if( OK ) {
			Resfresh();
		}
	}
	
	void PanelListClick(object sender, EventArgs e)
	{
		panelList.Select();
		SelectObj = null;
	}
	
	void MainFormFormClosing(object sender, FormClosingEventArgs e)
	{
		
	}
	
	void Timer1Tick(object sender, EventArgs e)
	{
		if( Math.Abs( LY - CY ) > 2.99 ) {
			float off = (CY - LY) / 10;
			if( off < 0 ) {
				off += -3;
			}
			if( off > 0 ) {
				off += 3;
			}
			LY += off;
			mf.panelList.AutoScrollPosition = new Point( 0, (int)LY );
		}
		else {
			LY = CY;
			mf.panelList.AutoScrollPosition = new Point( 0, (int)LY );
			timer1.Enabled = false;
		}
	}
	
	void LinkLabel1LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
	{
		string Web = "www.linkboy.cc/course.html";
		System.Diagnostics.Process.Start( "http://" + Web );
	}
}
}

